#include"Video.h"
/****************************************************************************
 *  Name       : putChar
 *  Parameters : X position
 *               Y position
 *               Character to be displayed
 *               Attribute to be used
 *  Returns    : Nothing
 *  Purpose    : Puts a character at the specified position with specified
 *               attribute.
 ****************************************************************************/
void putChar(int x, int y, char c, int attr)
{
	char far *vBuf = Video + (80 * 2 * y) + (2 * x);
	*(vBuf++) = c;
	*vBuf = attr;
}
/****************************************************************************
 *  Name       : putChar
 *  Parameters : X position
 *               Y position
 *               Character to be displayed
 *               Color of the character
 *               Background color of the character
 *               Blink (1 to blink and 0 otherwise)
 *  Returns    : Nothing
 *  Purpose    : Puts a character at specified position with specified
 *               colors.
 ****************************************************************************/
void putChar(int x, int y, char c, int cCol, int bCol, int blink = 0)
{
	char far *vBuf = Video + (80 * 2 * y) + (2 * x);
	char attr = cCol + ((bCol & 0x7) << 4) + (blink << 7);
	*(vBuf++) = c;
	*vBuf = attr;
}
/****************************************************************************
 *  Name       : highlightChar
 *  Parameters : X position
 *               Y position
 *               Highlight color
 *  Returns    : Nothing
 *  Purpose    : Highlights a character by setting its background color to
 *               the specified highlight color.
 ****************************************************************************/
void highlightChar(int x, int y, int hCol)
{
	char far *vBuf = Video + (80 * 2 * y) + (2 * x) + 1;
	char attr = (*vBuf & 0x0f) + ((hCol & 0x7)<<4);
	*vBuf = attr;
}
/****************************************************************************
 *  Name       : putStr
 *  Parameters : X position
 *               Y position
 *               String to be displayed
 *               Attribute of normal text
 *               Attribute of hotkey text
 *  Returns    : Nothing
 *  Purpose    : To display a string.
 ****************************************************************************/
void putStr(int x, int y, char *str, int attr, int hAttr)
{
	int i, off, len;
	len = strlen(str);
	for ( i = 0, off = 0; i < len; i++, off++ )
	{
		if ( str[i] == '&' ) // If hotkey
		{
			i++;
			putChar(x + off, y, str[i], hAttr); // Use hotkey attribute
		}
		else
			putChar(x + off, y, str[i], attr);
	}
}
/****************************************************************************
 *  Name       : putStr
 *  Parameters : X position
 *               Y position
 *               String to be displayed
 *               Color of normal text
 *               Background color of normal text
 *               Color of hotkey text
 *               Background of hotkey text
 *               Blink
 *  Returns    : Nothing
 *  Purpose    : Displays a string.
 ****************************************************************************/
void putStr(int x, int y, char *str, int cCol, int bCol, int hCol, int hbCol, int blink = 0)
{
	int i, off, len;
	len = strlen(str);
	for ( i = 0, off = 0; i < len; i++, off++ )
	{
		if ( str[i] == '&' )
		{
			i++;
			putChar(x + off, y, str[i], hCol, hbCol, blink);
		}
		else
			putChar(x + off, y, str[i], cCol, bCol, blink);
	}
}
/****************************************************************************
 *  Name       : drawSingleBox
 *  Parameters : Left of the Box
 *               Top of the Box
 *               Right of the Box
 *               Bottom of the Box
 *               Attribute to draw the Box
 *  Returns    : Nothing
 *  Purpose    : To draw a Box with single line border, with extra padding
 *               in the left and right.  (Mainly used by Menu)
 ****************************************************************************/
void drawSingleBox(int left, int top, int right, int bottom, char attr)
{
	int i;
	putChar(left + 1, top, SNGL_TL, attr); // corner box chars
	putChar(right - 1, top, SNGL_TR, attr);
	putChar(left + 1, bottom, SNGL_BL, attr);
	putChar(right - 1, bottom, SNGL_BR, attr);
	putChar(left, top, ' ', attr); // corner fillers
	putChar(right, top, ' ', attr);
	putChar(left, bottom, ' ', attr);
	putChar(right, bottom, ' ', attr);
	for ( i = left + 2; i < right - 1; i++ ) // top and bottom horizontal lines
	{
		putChar(i, top, SNGL_H, attr);
		putChar(i, bottom, SNGL_H, attr);
	}
	for ( i = top + 1; i < bottom; i++ )
	{
		putChar(left, i, ' ', attr); // fillers
		putChar(right, i, ' ', attr);
		putChar(left + 1, i, SNGL_V, attr); // vertical lines
		putChar(right - 1, i, SNGL_V, attr);
	}
}
/****************************************************************************
 *  Name       : drawSingleBox
 *  Parameters : Left of the Box
 *               Top of the Box
 *               Right of the Box
 *               Bottom of the Box
 *               Color of the boundary
 *               Background color of the boundary
 *  Returns    : Nothing
 *  Purpose    : To draw a Box with single line border, with extra padding
 *               in the left and right.  (Mainly used by Menu)
 ****************************************************************************/
void drawSingleBox(int left, int top, int right, int bottom, int fCol, int bCol)
{
	char attr = fCol + ((bCol & 0x7)<<4);
	drawSingleBox(left, top, right, bottom, attr);
}
/****************************************************************************
 *  Name       : drawDoubleBox
 *  Parameters : Left of the Box
 *               Top of the Box
 *               Right of the Box
 *               Bottom of the Box
 *               Attribute to draw the Box
 *  Returns    : Nothing
 *  Purpose    : To draw a Box with double line border, with extra padding
 *               in the left and right.
 ****************************************************************************/
void drawDoubleBox(int left, int top, int right, int bottom, char attr)
{
	int i;
	putChar(left + 1, top, DBL_TL, attr); // corner box chars
	putChar(right - 1, top, DBL_TR, attr);
	putChar(left + 1, bottom, DBL_BL, attr);
	putChar(right - 1, bottom, DBL_BR, attr);
	putChar(left, top, ' ', attr); // corner fillers
	putChar(right, top, ' ', attr);
	putChar(left, bottom, ' ', attr);
	putChar(right, bottom, ' ', attr);
	for ( i = left + 2; i < right - 1; i++ ) // top and bottom horizontal lines
	{
		putChar(i, top, DBL_H, attr);
		putChar(i, bottom, DBL_H, attr);
	}
	for ( i = top + 1; i < bottom; i++ )
	{
		putChar(left, i, ' ', attr); // fillers
		putChar(right, i, ' ', attr);
		putChar(left + 1, i, DBL_V, attr); // vertical lines
		putChar(right - 1, i, DBL_V, attr);
	}
}
/****************************************************************************
 *  Name       : drawDoubleBox
 *  Parameters : Left of the Box
 *               Top of the Box
 *               Right of the Box
 *               Bottom of the Box
 *               Color of the boundary
 *               Background color of the boundary
 *  Returns    : Nothing
 *  Purpose    : To draw a Box with double line border, with extra padding
 *               in the left and right.
 ****************************************************************************/
void drawDoubleBox(int left, int top, int right, int bottom, int fCol, int bCol)
{
	char attr = fCol + ((bCol & 0x7)<<4);
	drawDoubleBox(left, top, right, bottom, attr);
}
/****************************************************************************
 *  Name       : drawSingleRect
 *  Parameters : Rectangle coordinates
 *               Attribute of the boundary chars
 *  Returns    : Nothing
 *  Purpose    : To draw a Rectangle with single line border with no padding.
 ****************************************************************************/
void drawSingleRect(Rectangle win, char attr)
{
	int i;
	putChar(win.left, win.top, SNGL_TL, attr);
	putChar(win.right, win.top, SNGL_TR, attr);
	putChar(win.left, win.bottom, SNGL_BL, attr);
	putChar(win.right, win.bottom, SNGL_BR, attr);
	for ( i = win.left + 1; i < win.right; i++ )
	{
		putChar(i, win.top, SNGL_H, attr);
		putChar(i, win.bottom, SNGL_H, attr);
	}
	for ( i = win.top + 1; i < win.bottom; i++ )
	{
		putChar(win.left, i, SNGL_V, attr);
		putChar(win.right, i, SNGL_V, attr);
	}
}
/****************************************************************************
 *  Name       : drawDoubleRect
 *  Parameters : Rectangle coordinates
 *               Attribute of the boundary chars
 *  Returns    : Nothing
 *  Purpose    : To draw a Rectangle with double line border with no padding.
 ****************************************************************************/
void drawDoubleRect(Rectangle win, char attr)
{
	int i;
	putChar(win.left, win.top, DBL_TL, attr);
	putChar(win.right, win.top, DBL_TR, attr);
	putChar(win.left, win.bottom, DBL_BL, attr);
	putChar(win.right, win.bottom, DBL_BR, attr);
	for ( i = win.left + 1; i < win.right; i++ )
	{
		putChar(i, win.top, DBL_H, attr);
		putChar(i, win.bottom, DBL_H, attr);
	}
	for ( i = win.top + 1; i < win.bottom; i++ )
	{
		putChar(win.left, i, DBL_V, attr);
		putChar(win.right, i, DBL_V, attr);
	}
}
/****************************************************************************
 *  Name       : drawSingleRect
 *  Parameters : Rectangle coordinates
 *               Color the boundary chars
 *               Background color of the boundary chars
 *  Returns    : Nothing
 *  Purpose    : To draw a Rectangle with single line border with no padding.
 ****************************************************************************/
void drawSingleRect(Rectangle win, int Fcol, int Bcol)
{
	char attr = (Fcol & 0xff) + ((Bcol & 0xf) << 4);
	drawSingleRect(win, attr);
}
/****************************************************************************
 *  Name       : drawDoubleRect
 *  Parameters : Rectangle coordinates
 *               Color of the boundary chars
 *               Background color of the boundary chars
 *  Returns    : Nothing
 *  Purpose    : To draw a Rectangle with double line border with no padding.
 ****************************************************************************/
void drawDoubleRect(Rectangle win, int Fcol, int Bcol)
{
	char attr = (Fcol & 0xff) + ((Bcol & 0xf) << 4);
	drawDoubleRect(win, attr);
}
/****************************************************************************
 *  Name       : fillBox
 *  Parameters : Left of the Box
 *               Top of the Box
 *               Right of the Box
 *               Bottom of the Box
 *               Attribute of the boundary chars
 *  Returns    : Nothing
 *  Purpose    : Fills an area specified by the parameters.
 *               Ideal case shown below.
 *               eg. drawSingleBox(l, t, r, b, attr);
 *                   fillBox(l + 2, t + 1, r - 1, b, col);
 ****************************************************************************/
void fillBox(int left, int top, int right, int bottom, int attr)
{
	int i, j;
	attr = attr + ((attr & 0x7)<<4);
	for ( j = top; j < bottom; j++ )
	{
		for ( i = left; i < right; i++ )
			putChar(i, j, ' ', attr);
	}
}
/****************************************************************************
 *  Name       : fillBox
 *  Parameters : Rectangle to be filled
 *               Color / Attribute to be used
 *  Returns    : Nothing
 *  Purpose    : Fills the rectangle specified with the specified color.
 *               Same as the above fillBox.
 ****************************************************************************/
void fillBox(Rectangle win, int attr)
{
	int i, j;
	attr = attr + ((attr & 0x7)<<4);
	for ( j = win.top; j < win.bottom; j++ )
	{
		for ( i = win.left; i < win.right; i++ )
			putChar(i, j, ' ', attr);
	}
}
/****************************************************************************
 *  Name       : fillBox
 *  Parameters : Rectangle to be filled
 *               Character to be filled
 *               Color / Attribute to be used
 *  Returns    : Nothing
 *  Purpose    : Fills the rectangle specified with the specified color.
 *               Same as the above fillBox.
 ****************************************************************************/
void fillBox(int left, int top, int right, int bottom, char c, int attr)
{
	int i, j;
	attr = attr + ((attr & 0x7)<<4);
	for ( j = top; j < bottom; j++ )
	{
		for ( i = left; i < right; i++ )
			putChar(i, j, c, attr);
	}
}
/****************************************************************************
 *  Name       : normalScreen
 *  Parameters : None
 *  Returns    : Nothing
 *  Purpose    : Restores the normal screen attribute.
 ****************************************************************************/
void normalScreen()
{
	int x, y;
	char far *vBuf;
	vBuf = Video;
	for ( y = 0; y < 25; y++ )
	{
		for ( x = 0; x < 80; x++ )
		{
			*(vBuf + (y * 160) + (x * 2) + 1) = 0x07;
		}
	}
}
/****************************************************************************
 *  Name       : closeScreen
 *  Parameters : None
 *  Returns    : Nothing
 *  Purpose    : Closes the screen from left and right.
 ****************************************************************************/
void closeScreen()
{
	int x, y;
	for ( x = 0; x < 40; x++ )
	{
		for ( y = 0; y < 25; y++ )
		{
			putChar(x, y, ' ', 0x07);
			putChar((80 - x - 1), y, ' ', 0x07);
		}
		delay(100);
	}
}
void closeScreenVertical()
{
	int x, y;
	for ( y = 0; y < 13; y++ )
	{
		for ( x = 0; x < 80; x++ )
		{
			putChar(x, y, ' ', 0x07);
			putChar(x, 24 - y, ' ', 0x07);
		}
		delay(100);
	}
}
/****************************************************************************
 *  Name       : saveRect
 *  Parameters : Rectangle to be saved
 *  Returns    : Character Pointer
 *  Purpose    : Saves the screen contents specified by the Rectangle and
 *               returns a pointer to where the contents are stored.
 ****************************************************************************/
char *saveRect(Rectangle win)
{
	int width  = win.right - win.left + 1,
			height = win.bottom - win.top + 1,
			x, y, index = 0;
	char *videoBuffer;
	videoBuffer = (char *) malloc(width * height * 2);
	if ( videoBuffer != NULL )
	{
		for ( y = win.top; y <= win.bottom; y++ )
		{
			for ( x = win.left; x <= win.right; x++ )
			{
				videoBuffer[index++] = *(Video + (160 * y) + (2 * x));
				videoBuffer[index++] = *(Video + (160 * y) + (2 * x) + 1);
			}
		}
	} // Endif
	return videoBuffer;
}
/****************************************************************************
 *  Name       : restoreRect
 *  Parameters : Rectangle to be restored
 *               Pointer to the memory area where the screen contents were
 *                 stored before
 *  Returns    : Nothing
 *  Purpose    : Restores screen contents to required position on screen.
 ****************************************************************************/
void restoreRect(Rectangle win, char *videoBuffer)
{
	int x, y, index = 0;
	if ( videoBuffer != NULL )
	{
		for ( y = win.top; y <= win.bottom; y++ )
		{
			for ( x = win.left; x <= win.right; x++ )
			{
				*(Video + (160 * y) + (2 * x)) = videoBuffer[index++];
				*(Video + (160 * y) + (2 * x) + 1) = videoBuffer[index++];
			}
		}
	} // Endif
}
